package com.dongdongshop.mq;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.dongdongshop.pojo.TbOrder;
import com.dongdongshop.pojo.TbPayLog;
import com.dongdongshop.service.OrderService;
import com.dongdongshop.service.PayLogService;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

@RocketMQTransactionListener(txProducerGroup = "down_order")
public class LocalTranstion  implements RocketMQLocalTransactionListener {
    @Resource
    private PayLogService payLogService;
    @Resource
    private OrderService orderService;
    @Resource
    private RedisTemplate redisTemplate;
    private Logger logger = LoggerFactory.getLogger(LocalTranstion.class);

    /**
     * 1、MQ服务，成功接到事物消息后，执行本方法；
     * 2、处理本地事物，并将本地事物处理结果返回给MQ服务
     *
     * @return COMMIT, ROLLBACK, UNKNOWN;
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        //将本地事物执行状态return到MQ服务，并且保存到redis备份（网络延迟，MQ服务产生回调的时候 可以从redis中获取）
        try {
            //业务处理
            Map<String,Object> map = (Map<String, Object>)o;
            String tradeNo = (String)map.get("tradeNo");
            String trade_no = (String)map.get("trade_no");
            Double total = (Double) map.get("total");
            List<TbOrder> list = orderService.getByTradeNo(tradeNo);
            String ids = "";
            for (TbOrder tbOrder : list) {
                tbOrder.setStatus("2");
                orderService.updateStatu(tbOrder);
                ids += "," + tbOrder.getOrderId();
            }
            ids = ids.substring(1);
            //生成日志表
            TbPayLog tbPayLog = new TbPayLog();
            tbPayLog.setOutTradeNo(tradeNo);
            tbPayLog.setCreateTime(new Date());
            tbPayLog.setPayTime(new Date());
            tbPayLog.setTotalFee(total.longValue());
            tbPayLog.setUserId(list.get(0).getUserId());
            tbPayLog.setTransactionId(trade_no);
            tbPayLog.setTradeState("2");
            tbPayLog.setOrderList(ids);
            tbPayLog.setPayType("1");
            payLogService.addinfo(tbPayLog);
            logger.info("本地事物处理成功");
        } catch (Exception e) {
            //处理异常返回ROLLBACK
            redisTemplate.opsForValue().set(message.getHeaders().get("TRANSACTION_ID"), "2");
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        //处理成功返回COMMIT
        redisTemplate.opsForValue().set(message.getHeaders().get("TRANSACTION_ID"), "1");
        return RocketMQLocalTransactionState.COMMIT;
    }


    /**
     * MQ服务 由于网络等原因 未收到 本地事物处理结果，回查本地事物处理结果
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        //通过事务id获取 redis中 对应的本地事务执行状态
        String status = (String) redisTemplate.opsForValue().
                get(message.getHeaders().get("TRANSACTION_ID").toString());
        if ("1".equals(status)) {
            return RocketMQLocalTransactionState.COMMIT;
        } else if ("2".equals(status)) {
            //继续处理，或者直接回滚
            return RocketMQLocalTransactionState.ROLLBACK;
        } else {
            return RocketMQLocalTransactionState.UNKNOWN;
        }
    }

}
